#include "stdafx.h"
#include <stdio.h>
#include <stdarg.h>
#include <sys/stat.h>
#include "h2base.h"
#include "h2log.h"


bool file_log::backup_log()
{
    STRING::unicode filename(_filename);
    STRING::unicode new_filename(MAX_PATH);

    wchar_t* postfix = wcsrchr(*filename, L'.');
    wchar_t* pos_s1 = wcsrchr(*filename, L'/');
    wchar_t* pos_s2 = wcsrchr(*filename, L'\\');
    if(postfix && postfix > pos_s1 && postfix > pos_s2)
    {
        *postfix = 0;
        postfix++;
    }
    else
    {
        postfix =  NULL;
    }

    new_filename = filename + H2APP::time_stamp(L".%Y%m%d%H%M%S");

    if(postfix)
    {
        STRING::cat(new_filename, postfix);
    }
    return 0 == _wrename(*_filename, *new_filename);
}


bool file_log::write(const char* pszlog)
{
    // Rename file in case of file size exceeds threshold
    if(H2APP::file_size(_filename) >= _max_file_size)
    {
        close();
        backup_log();
        open();
    }

    for(int i_try = 0; i_try < 2; ++i_try)
    {
        if(NULL != _fp && fwrite(pszlog, strlen(pszlog), 1, _fp) > 0)
        {
            // Write log succeed
            return true;
        }
        
        // Re-open the file in case of failure
        close();
        open();
    }

    return false;
}





int              LOG::_debug_flag = 0;
LOG::output_func LOG::_output_func = NULL;
file_log         LOG::log_file, LOG::debug_file, LOG::error_file;


bool LOG::log(const char* pzLog, ...)
{
    // if file name is null then initialize it by application name
    if(0 == *log_file.get_filename())
    {
        STRING::unicode filename(MAX_PATH);
        filename = H2APP::app_path() + H2APP::app_name() + L".log";
        log_file.set_filename(*filename);
    }

    bool res = true;
    STRING::ansi timestr = H2APP::time_stamp(L"[%Y-%m-%d %H:%M:%S] ");
    res &= log_file.write(*timestr);
    res &= output(*STRING::unicode(*timestr));

    STRING::ansi text(MAX_STR_BUF);
	va_list argp;
	va_start(argp, pzLog);
    vsnprintf_s(*text, text.size(), _TRUNCATE, pzLog, argp);
    va_end(argp);

    res &= log_file.write(*text);
    res &= output(*STRING::unicode(*text));
    res &= log_file.write("\n");
    res &= output(L"\n");
    return res;
}


bool LOG::debug(int debug_flag, const char* pzlog, ...)
{
    // return if iDebugFlag not matched
    if((debug_flag & _debug_flag) != debug_flag)
    {
        return 0;
    }

    // if file name is null then initialize it by application name
    if(0 == *debug_file.get_filename())
    {
        STRING::unicode filename(MAX_PATH);
        filename = H2APP::app_path() + H2APP::app_name() + L"_debug.log";
        debug_file.set_filename(*filename);
    }


    bool res = true;
    STRING::ansi timestr = H2APP::time_stamp(L"[%Y-%m-%d %H:%M:%S] ");
    res &= debug_file.write(*timestr);

    STRING::ansi text(MAX_STR_BUF);
	va_list argp;
	va_start(argp, pzlog);
    vsnprintf_s(*text, text.size(), _TRUNCATE, pzlog, argp);
    va_end(argp);

    res &= debug_file.write(*text);
    res &= debug_file.write("\n");

    return res;
}


bool LOG::error(int errcode, const char* pzlog, ...)
{
    // if file name is null then initialize it by application name
    if(0 == *error_file.get_filename())
    {
        STRING::unicode filename(MAX_PATH);
        filename = H2APP::app_path() + H2APP::app_name() + L"_err.log";

        error_file.set_filename(*filename);
    }

    bool res = true;
    STRING::ansi timestr = H2APP::time_stamp(L"[%Y-%m-%d %H:%M:%S] ");
    res &= log_file.write(*timestr);
    res &= error_file.write(*timestr);

    STRING::ansi text(MAX_STR_BUF);
    sprintf_s(*text, text.size(), "[ERROR:%d]", errcode);
    res &= log_file.write(*text);
    res &= error_file.write(*text);

	va_list argp;
	va_start(argp, pzlog);
    vsnprintf_s(*text, text.size(), _TRUNCATE, pzlog, argp);
    va_end(argp);

    res &= log_file.write(*text);
    res &= log_file.write("\n");
    res &= output(*STRING::unicode(*text));
    res &= error_file.write(*text);
    res &= error_file.write("\n");

    return res;
}

